﻿#include "Mortonizer.h"

unsigned int mortonize(unsigned int x, unsigned int y, unsigned int z)
{
    x =               x & 0x000003FF; // 0000 0000 0000 0000 0000 0011 1111 1111
    x = (x | (x << 16)) & 0x030000FF; // 0000 0011 0000 0000 0000 0000 1111 1111
    x = (x | (x <<  8)) & 0x0300F00F; // 0000 0011 0000 0000 1111 0000 0000 1111
    x = (x | (x <<  4)) & 0x030C30C3; // 0000 0011 0000 1100 0011 0000 1100 0011
    x = (x | (x <<  2)) & 0x09249249; // 0000 1001 0010 0100 1001 0010 0100 1001

    y =               y & 0x000003FF;
    y = (y | (y << 16)) & 0x030000FF;
    y = (y | (y <<  8)) & 0x0300F00F;
    y = (y | (y <<  4)) & 0x030C30C3;
    y = (y | (y <<  2)) & 0x09249249;

    z =               z & 0x000003FF;
    z = (z | (z << 16)) & 0x030000FF;
    z = (z | (z <<  8)) & 0x0300F00F;
    z = (z | (z <<  4)) & 0x030C30C3;
    z = (z | (z <<  2)) & 0x09249249;

    return x | (y << 1) | (z << 2);
}

void demortonize(unsigned int m, unsigned int &x, unsigned int &y, unsigned int &z)
{
    x =             m & 0x09249249; // 0000 1001 0010 0100 1001 0010 0100 1001
    x = (x | x >>  2) & 0x030C30C3; // 0000 0011 0000 1100 0011 0000 1100 0011
    x = (x | x >>  4) & 0x0300F00F; // 0000 0011 0000 0000 1111 0000 0000 1111
    x = (x | x >>  8) & 0x030000FF; // 0000 0011 0000 0000 0000 0000 1111 1111
    x = (x | x >> 16) & 0x000003FF; // 0000 0000 0000 0000 0000 0011 1111 1111

    y =      (m >> 1) & 0x09249249;
    y = (y | y >>  2) & 0x030C30C3;
    y = (y | y >>  4) & 0x0300F00F;
    y = (y | y >>  8) & 0x030000FF;
    y = (y | y >> 16) & 0x000003FF;

    z =      (m >> 2) & 0x09249249;
    z = (z | z >>  2) & 0x030C30C3;
    z = (z | z >>  4) & 0x0300F00F;
    z = (z | z >>  8) & 0x030000FF;
    z = (z | z >> 16) & 0x000003FF;
}

unsigned int mortonize(unsigned int x, unsigned int y)
{
    x =              x & 0x0000FFFF; // 0000 0000 0000 0000 1111 1111 1111 1111
    x = (x | (x << 8)) & 0x00FF00FF; // 0000 0000 1111 1111 0000 0000 1111 1111
    x = (x | (x << 4)) & 0x0F0F0F0F; // 0000 1111 0000 1111 0000 1111 0000 1111
    x = (x | (x << 2)) & 0x33333333; // 0011 0011 0011 0011 0011 0011 0011 0011
    x = (x | (x << 1)) & 0x55555555; // 0101 0101 0101 0101 0101 0101 0101 0101

    y =              y & 0x0000FFFF;
    y = (y | (y << 8)) & 0x00FF00FF;
    y = (y | (y << 4)) & 0x0F0F0F0F;
    y = (y | (y << 2)) & 0x33333333;
    y = (y | (y << 1)) & 0x55555555;

    return x | (y << 1);
}

void demortonize(unsigned int m, unsigned int &x, unsigned int &y)
{
    x =              m & 0x55555555; // 0101 0101 0101 0101 0101 0101 0101 0101
    x = (x | (x >> 1)) & 0x33333333; // 0011 0011 0011 0011 0011 0011 0011 0011
    x = (x | (x >> 2)) & 0x0F0F0F0F; // 0000 1111 0000 1111 0000 1111 0000 1111
    x = (x | (x >> 4)) & 0x00FF00FF; // 0000 0000 1111 1111 0000 0000 1111 1111
    x = (x | (x >> 8)) & 0x0000FFFF; // 0000 0000 0000 0000 1111 1111 1111 1111

    y =       (m >> 1) & 0x55555555;
    y = (y | (y >> 1)) & 0x33333333;
    y = (y | (y >> 2)) & 0x0F0F0F0F;
    y = (y | (y >> 4)) & 0x00FF00FF;
    y = (y | (y >> 8)) & 0x0000FFFF;
}
